package com.ruoyi.web.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.config.RedissonLockComponent;
import com.ruoyi.common.enums.BusinessEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.domain.Product;
import com.ruoyi.system.domain.ProductKey;
import com.ruoyi.web.controller.vo.AddProductKeyVo;
import com.ruoyi.system.mapper.ProductKeyMapper;
import com.ruoyi.web.controller.vo.UpdateKeyVo;
import com.ruoyi.web.service.ISysProductKeySevice;
import com.ruoyi.web.service.ISysProductSevice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

@Service
public class SysProductKeyServiceImpl extends ServiceImpl<ProductKeyMapper, ProductKey> implements ISysProductKeySevice {

    @Autowired
    private ISysProductSevice sysProductSevice;
    @Autowired
    private RedissonLockComponent redissonLockComponent;

    @Override
    @Transactional
    public Long addProductKey(List<AddProductKeyVo> addProductKeyVos) {
        if (Objects.isNull(addProductKeyVos)) {
            throw new ServiceException("请传入商品卡密");
        }
        // 过滤掉未填写的数据
        List<AddProductKeyVo> productKeyVos = addProductKeyVos.parallelStream()
                .filter(vo ->
                        Objects.nonNull(vo.getProductId())
                        && StrUtil.isNotBlank(vo.getKey())
                        && StrUtil.isNotBlank(vo.getSeparate())
                        && vo.getKey().contains(vo.getSeparate())
                        && !StrUtil.startWith(vo.getKey(), vo.getSeparate()))
                .collect(Collectors.toList());
        if (CollectionUtil.isEmpty(productKeyVos)) {
            return 0L;
        }

        AtomicLong countAutomic = new AtomicLong(0);
        // 查找数据库中已经存在的
        List<String> prefixKeys = productKeyVos.parallelStream()
                .map(vo -> StrUtil.split(vo.getKey(), vo.getSeparate()).get(0))
                .filter(StrUtil::isNotBlank)
                .collect(Collectors.toList());

        List<String> dbPrefixKeys = this.list(
                Wrappers.lambdaQuery(ProductKey.class)
                        .in(ProductKey::getPrefixKey, prefixKeys)
        ).stream()
                .map(ProductKey::getPrefixKey)
                .collect(Collectors.toList());
        List<ProductKey> productKeys = new ArrayList<>();
        HashSet<Long> productIdSets = new HashSet<>();
        productKeyVos.parallelStream().forEach(productKeyVo -> {
            // 数据库中存在相同的卡密前缀
            if (CollectionUtil.contains(dbPrefixKeys, StrUtil.split(productKeyVo.getKey(), productKeyVo.getSeparate()).get(0))) {
                return;
            }
            Product product = sysProductSevice.getById(productKeyVo.getProductId());
            if (BusinessEnum.ProductType.RECHARGE.getCode().equals(product.getType())) {
                throw new ServiceException("存在非售卖商品，请勿添加卡密");
            }
            ProductKey productKey = new ProductKey();
            productKey.setPrefixKey(StrUtil.split(productKeyVo.getKey(), productKeyVo.getSeparate()).get(0));
            productIdSets.add(productKeyVo.getProductId());
            productKey.setProductId(productKeyVo.getProductId());
            productKey.setCardKey(productKeyVo.getKey());
            productKey.setCreateTime(new Date());
            productKeys.add(productKey);
            countAutomic.incrementAndGet();
        });
        this.saveBatch(productKeys);

        // 更新商品卡密实际库存数量
        sysProductSevice.updateStockHasLock(new ArrayList<Long>(productIdSets));
        return countAutomic.get();
    }

    @Override
    public List<ProductKey> queryNotSelledProductKey(Long productId) {
        return this.list(
                Wrappers.lambdaQuery(ProductKey.class)
                        .eq(ProductKey::getProductId, productId)
                        .eq(ProductKey::getIsSell, "N")
        );

    }
    @Override
    @Transactional
    public void delete(List<Long> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            throw new ServiceException("请选择需要删除的卡密");
        }
        List<ProductKey> productKeys = this.listByIds(ids);
        if (productKeys.parallelStream().anyMatch(key -> "Y".equals(key.getIsSell()))) {
            throw new ServiceException("只能删除未卖出的卡密");
        }
        this.removeBatchByIds(ids);
        List<Long> collect = productKeys.stream()
                .map(ProductKey::getProductId)
                .distinct()
                .collect(Collectors.toList());
        // 库存重新统计
        sysProductSevice.updateStockHasLock(collect);
    }

    @Override
    @Transactional
    public void updateKey(UpdateKeyVo updateKeyVo) {
        ProductKey productKey = this.getById(updateKeyVo.getId());
        Optional.ofNullable(productKey).orElseThrow(() -> new ServiceException("卡密数据不存在"));
        Optional.ofNullable(StrUtil.emptyToNull(updateKeyVo.getKey())).orElseThrow(() -> new ServiceException("卡密为空"));
        Optional.ofNullable(StrUtil.emptyToNull(updateKeyVo.getSeparate())).orElseThrow(() -> new ServiceException("分隔符为空"));
        if (!updateKeyVo.getKey().contains(updateKeyVo.getSeparate())
                || StrUtil.startWith(updateKeyVo.getKey(), updateKeyVo.getSeparate())) {
            throw new ServiceException("当前卡密不符合分隔符规则");
        }
        String prefixKey = updateKeyVo.getKey().split(updateKeyVo.getSeparate())[0];
        // 查看卡密是否存在
        List<ProductKey> productKeys = this.list(
                Wrappers.lambdaQuery(ProductKey.class)
                        .eq(ProductKey::getPrefixKey, prefixKey)
                        .ne(ProductKey::getId, productKey.getId())
        );
        if (CollectionUtil.isNotEmpty(productKeys)) {
            throw new ServiceException("根据卡密前缀规则，找到已存在卡密");
        }
        this.update(
                Wrappers.lambdaUpdate(ProductKey.class)
                        .set(ProductKey::getPrefixKey, prefixKey)
                        .set(ProductKey::getCardKey, updateKeyVo.getKey())
                        .eq(ProductKey::getId, updateKeyVo.getId())
        );
    }

    @Override
    @Transactional
    public void updateSellStatus(List<Long> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            throw new ServiceException("请选择未卖出的卡密");
        }
        // 需要防止并发时，当前卡密正在卖出
        Map<Long, List<ProductKey>> productKeyMap = this.listByIds(ids).stream()
                .filter(key -> "N".equals(key.getIsSell()))
                .collect(Collectors.groupingBy(key -> key.getProductId()));

        productKeyMap.forEach((productId, productkeys) -> {

            redissonLockComponent.execByDistributedLock("update_stock:" + productId, 2L, () ->{
                this.update(
                        Wrappers.lambdaUpdate(ProductKey.class)
                                .set(ProductKey::getIsSell, "Y")
                                .in(ProductKey::getId,
                                        productkeys.stream().map(ProductKey::getId).collect(Collectors.toList())
                                )
                );
                // 更新productId库存
                 sysProductSevice.updateStockNoLock(Arrays.asList(productId));
                 return true;
             });
        });


    }

}
